package rpcbiz

import (
	"errors"
	"fmt"
	"time"
	"github.com/astaxie/beego/logs"
	"cloud_worm/util/unet/rpc"
	"cloud_worm/wormweb/controllers/ctrconfig"
	"cloud_worm/util/umodels/mysqldb/dbmanager"
	"cloud_worm/util/umodels/mysqldb"
	"cloud_worm/util/uconst"
	"cloud_worm/util/proto/urpc"
	"cloud_worm/util/proto/ujson"
	"cloud_worm/util/third/unotify"
	"cloud_worm/wormweb/controllers/ctrsecurity/monitor"
	"cloud_worm/wormweb/controllers/ctrinner/taskqueue"
	"cloud_worm/wormweb/controllers/ctrsecurity/autocheck"
	"cloud_worm/wormweb/controllers/ctrsecurity/webtask/slowtask"
)


type AgentEventPostArgs urpc.AgentEventPostArgs

func (args *AgentEventPostArgs) param() error {
	if len(args.AgentId) != uconst.AgentIdLen {
		return errors.New("agent id error")
	}
	return nil
}

func (w *AgentEvent) doSomethingForOffline(args *AgentEventPostArgs, msg string)  {

	if IMPostEnable == true {
		item := &unotify.IMNotifyItem{
			Grade: unotify.WarnGrade,
			Title: unotify.DefaultTitle,
			Msg: msg,
			IMUsers: []string {
				"用学",
			},
		}
		unotify.IMNotifyInst.SendAsync(item)
	}

	// TODO: 下线相关的事项
	return
}

func (w *AgentEvent) doSomethingForOnline(args *AgentEventPostArgs, msg string)  {
	if IMPostEnable == true {
		item := &unotify.IMNotifyItem{
			Grade: unotify.InfoGrade,
			Title: unotify.DefaultTitle,
			Msg: msg,
			IMUsers: []string {
				"用学",
			},
		}
		unotify.IMNotifyInst.SendAsync(item)

		// 异步插入或者更新machine的信息
		updateMachine := &slowtask.UpdateMachineByCapital{
			IP: args.AgentIP,
			WormId: args.AgentId,
		}
		taskqueue.SlowQueueInst().ListC <- updateMachine
	}

	// 第二部分，才处理第三方的订阅处理，采用异步方式
	w.sendMonitorEnable(args)

	// 下发auto check操作
	if autocheck.CheckAutoForOnline {
		checkItem := &autocheck.NotifyAutoCheck{
			AgentIP: args.AgentIP,
			AgentID: args.AgentId,
		}
		taskqueue.SlowQueueInst().ListC <- checkItem
	}

	return
}

func (w *AgentEvent) sendMonitorEnable(args *AgentEventPostArgs)  {
	if monitor.AutoConfigForOnline == false {
		return
	}

	// 下发cmd monitor的配置
	// TODO: 使能和配置文件一起下发
	enablePayLoad := ujson.EnablePayLoad{
		Enable: monitor.CmdMonitor,
	}
	payLoad, err := enablePayLoad.MarshalJSON()
	if err != nil {
		logs.Error(fmt.Sprintf("cmd EnablePayLoad marshal json failed: %s", err.Error()))
		return
	}
	notifyItem := &monitor.NotifyAutoConfig{
		AgentID: args.AgentId,
		AgentIP: args.AgentIP,
		NotifyType: ujson.NtCmdMonitor,
		PayLoad: payLoad,
	}
	taskqueue.SlowQueueInst().ListC <- notifyItem

	// 下发file monitor的配置
	// TODO: 使能和配置文件一起下发
	enablePayLoad = ujson.EnablePayLoad{
		Enable: monitor.FileMonitor,
	}
	payLoad, err = enablePayLoad.MarshalJSON()
	if err != nil {
		logs.Error(fmt.Sprintf("file EnablePayLoad marshal json failed: %s", err.Error()))
		return
	}
	notifyItem = &monitor.NotifyAutoConfig{
		AgentID: args.AgentId,
		AgentIP: args.AgentIP,
		NotifyType: ujson.NtFileMonitor,
		PayLoad: payLoad,
	}
	taskqueue.SlowQueueInst().ListC <- notifyItem

	// 下发log collector的配置
	// TODO: 使能和配置文件一起下发
	enablePayLoad = ujson.EnablePayLoad{
		Enable: monitor.LogCollector,
	}
	payLoad, err = enablePayLoad.MarshalJSON()
	if err != nil {
		logs.Error(fmt.Sprintf("file EnablePayLoad marshal json failed: %s", err.Error()))
		return
	}
	notifyItem = &monitor.NotifyAutoConfig{
		AgentID: args.AgentId,
		AgentIP: args.AgentIP,
		NotifyType: ujson.NtLogCollector,
		PayLoad: payLoad,
	}
	taskqueue.SlowQueueInst().ListC <- notifyItem

	return
}

// AgentEvent.EventPost 提供 agent event post的服务
func (w *AgentEvent) EventPost(args *AgentEventPostArgs, reply *urpc.AgentEventPostReply) error {
	err := args.param()
	if err != nil {
		return err
	}

	if args.EventType == urpc.AgentEventOnline {
		// 上线事件
		// TT推送采用异步方式
		msg := fmt.Sprintf("| %d | %s | ONLINE |", args.Version, args.AgentIP)
		logs.Notice(msg)                                      // 考虑记录一条日志好了

		w.doSomethingForOnline(args, msg)
	} else if args.EventType == urpc.AgentEventOffline {
		// 下线事件
		msg := fmt.Sprintf("| %d | %s | OFFLINE |", args.Version, args.AgentIP,)
		logs.Notice(msg)

		w.doSomethingForOffline(args, msg)
	} else {
		return errors.New("agent event type error")
	}

	return nil
}

type AgentEvent int

func init()  {
	rpc.Register(new(AgentEvent))
}

// 对于agent上线后的系列动作，作为一个全局的配置，在设计access server的重启操作时，需要执行配置false操作
var IMPostEnable = false

const IMPostEnableName = "im_post_enable"

// 加载配置
func IMPostEnableLoad() error {
	conf := &dbmanager.WebConfig{Name: IMPostEnableName}
	if err := conf.Read("name"); err == nil {
		switch conf.Value {
		case "1", "t", "T", "true", "TRUE", "True", "YES", "yes", "Yes", "Y", "y", "ON", "on", "On":
			IMPostEnable = true
		case "0", "f", "F", "false", "FALSE", "False", "NO", "no", "No", "N", "n", "OFF", "off", "Off":
			IMPostEnable = false
		default:
			return fmt.Errorf("config value format error")
		}
	} else {
		return fmt.Errorf("读WebConfig(%s)错误: %s", IMPostEnableName, err.Error())
	}
	logs.Info(fmt.Sprintf("set %s=%v", IMPostEnableName, IMPostEnable))

	return nil
}

func init() {
	ctrconfig.RegisterConfigLoad(IMPostEnableName, IMPostEnableLoad)

	// 尝试创建该列数据
	conf := &dbmanager.WebConfig{Name: IMPostEnableName}
	if err := conf.Read("name"); err != nil {
		conf.Commit = "TT推送使能开关"
		conf.Type = dbmanager.BoolValue
		conf.Value = "false"
		conf.Created = time.Now().Unix()
		conf.Updated = conf.Created
		conf.Status = mysqldb.StatusValid
		conf.Insert()
	}

	IMPostEnableLoad()
}